/*
 * @Author: QiXiao
 * @Date: 2022-07-27 08:37:18
 * @FilePath: /openharmony/device/board/isoftstone/qihang/app/Qi_Xiao_Oled_demo/hx711/hx711.c
 * @Description: 
 */
#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "hi_io.h"
#include "hi_adc.h"
#include "hi_gpio.h"
#include "iot_errno.h"
#include "hx711.h"

#define HX711_TASK_GPIO_INPUT 7    //data
#define HX711_TASK_GPIO_OUTPUT 2   //clk
#define BEEP_GPIO_OUTPUT 5 //beep

#define HX711_TASK_STACK_SIZE 4096
#define HX711_TASK_PRIO 25

#define WEIGHT_NUMBER 10 // 采集个数

#define CONFIG_AD_MAX 24    //AD 读取长度
#define SCALEFACTOR 1 // 比例系数
#define TRANSFER_PERCENT 1034 // AD值与体重的转换比例(已校准)
#define CLEAR_WEIGHT 8420  //净重

unsigned long count=0;
int g_weight=0;

void Hx711_GPIO_Init(void)
{
    int ret;

    if((ret=IoTGpioInit(HX711_TASK_GPIO_INPUT))!=0){
        printf("hx711 data io init failed. ret=%d\n",ret);
    }
    else{
        printf("data io init success\n");
    }
    IoTGpioSetFunc(HX711_TASK_GPIO_INPUT, 0);
    if((ret=IoTGpioSetDir(HX711_TASK_GPIO_INPUT,IOT_GPIO_DIR_IN))!=HI_ERR_SUCCESS){
        printf("data io set dir failed. ret=%d\n",ret);
    }
    else{
        printf("data io set dir success\n");
    }

    if((ret=IoTGpioInit(HX711_TASK_GPIO_OUTPUT))!=0){
        printf("hx711 clk io init failed. ret=%d\n",ret);
    }
    else{
        printf("clk io init success");
    }
    IoTGpioSetFunc(HX711_TASK_GPIO_OUTPUT, 0);
    if((ret=IoTGpioSetDir(HX711_TASK_GPIO_OUTPUT,IOT_GPIO_DIR_OUT))!=HI_ERR_SUCCESS){
        printf("clk io set dir failed. ret=%d\n",ret);
    }
    else{
        printf("clk io set dir success\n");
    }
}

void Beep_GPIO_Init()
{
    int ret;
    if((ret=IoTGpioInit(BEEP_GPIO_OUTPUT))!=0){
        printf("beep io init failed. ret=%d\n",ret);
    }
    else{
        printf("beep io init success");
    }
    IoTGpioSetFunc(BEEP_GPIO_OUTPUT, 0);
    if((ret=IoTGpioSetDir(BEEP_GPIO_OUTPUT,IOT_GPIO_DIR_OUT))!=HI_ERR_SUCCESS){
        printf("beep io set dir failed. ret=%d\n",ret);
    }
    else{
        printf("beep io set dir success\n");
    }
}

static void *Hx711Task(const char *arg)
{
    (void)arg;
    while(1){
        int weight = (int)((float)(Filter_Data()*1.0)/TRANSFER_PERCENT-CLEAR_WEIGHT);
        weight=(weight>=0)?weight:0;
        printf("weight=%d\n",weight);
        g_weight=weight;
    }
}

static unsigned int Filter_Data(void)
{
    unsigned long weightBuf[WEIGHT_NUMBER];
    for(int i=0;i<WEIGHT_NUMBER;i++){
        count=0;
        unsigned short data=0;
        IoTGpioSetOutputVal(HX711_TASK_GPIO_OUTPUT,0);
        IoTGpioGetInputVal(HX711_TASK_GPIO_INPUT,&data);
        while(data == 1){
            IoTGpioGetInputVal(HX711_TASK_GPIO_INPUT,&data);
            //printf("data=%d",data);
        }
        for(int i=0;i<24;i++){
            IoTGpioSetOutputVal(HX711_TASK_GPIO_OUTPUT,1);
            for(int j=0;j++;j<20);
            count<<=1;
            IoTGpioSetOutputVal(HX711_TASK_GPIO_OUTPUT,0);
            for(int j=0;j++;j<20);
            IoTGpioGetInputVal(HX711_TASK_GPIO_INPUT,&data);
            //printf("data=%d \n",data);
            if(data){
                count++;
            }
        }
        IoTGpioSetOutputVal(HX711_TASK_GPIO_OUTPUT,1);
        count^=0x800000;
        for(int j=0;j++;j<20);
        IoTGpioSetOutputVal(HX711_TASK_GPIO_OUTPUT,0);
        //printf("once down");
        osDelay(5); //0.05s
        weightBuf[i]=count;
    }
    Sort_Data(weightBuf,WEIGHT_NUMBER);
    return weightBuf[((WEIGHT_NUMBER-1)/2)];
}

static void Sort_Data(float *buf,unsigned int length)
{
    int i,j;
    for(i=0;i<length;i++){
        for(j=0;j<length-i-1;j++){
            float tmp = buf[j];
            buf[j] = buf[j+1];
            buf[j+1]=tmp;
        }
    }
}

//采用返回值返回unsigned long总会Stack Overflow。。原因未知
/********原代码
unsigned long Get_Value(void)
{
    unsigned long count=0;
    unsigned short data=0;
    IoTGpioSetOutputVal(HX711_TASK_GPIO_OUTPUT,0);
    IoTGpioGetInputVal(HX711_TASK_GPIO_INPUT,&data);
    printf("ready getv\n");
    while(data == 0){
        for(int i=0;i<24;i++){
            IoTGpioSetOutputVal(HX711_TASK_GPIO_OUTPUT,1);
            for(int j=0;j++;j<20);
            count=(count<<1);
            IoTGpioSetOutputVal(HX711_TASK_GPIO_OUTPUT,0);
            for(int j=0;j++;j<20);
            IoTGpioGetInputVal(HX711_TASK_GPIO_INPUT,&data);
            //printf("data=%d \n",data);
            if(data){
                count++;
            }
        }
        printf("ready return count\n");
        printf("count1 = %lu\n",count);
        IoTGpioSetOutputVal(HX711_TASK_GPIO_OUTPUT,1);
        count = (count^0x800000);
        printf("count1 = %lu\n",count);
        for(int j=0;j++;j<20);
        IoTGpioSetOutputVal(HX711_TASK_GPIO_OUTPUT,0);
        osDelay(5); //0.05s
        printf("once down");
        return count;
    }
}
*******/

void beep_out(void)
{
    IoTGpioSetOutputVal(BEEP_GPIO_OUTPUT,1);
    sleep(3);
    IoTGpioSetOutputVal(BEEP_GPIO_OUTPUT,0);
}


void Hx711_Demo(void)
{
    osThreadAttr_t attr;
    Hx711_GPIO_Init();
    Beep_GPIO_Init();
    attr.name = "Hx711Task";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = HX711_TASK_STACK_SIZE;
    attr.priority = HX711_TASK_PRIO;
    if (osThreadNew((osThreadFunc_t)Hx711Task, NULL, &attr) == NULL) {
    printf("[Hx711_Demo] Falied to create LedTask!\n");
    }
}

APP_FEATURE_INIT(Hx711_Demo);